/************************************************
 * Copyright (c) 2007 ~ 2009, 
 * All rights reserved.
 * Version   : 1.0
 * Author    : lengsh@gmail.com 
 * Date      : 2009.1.2
 ************************************************/

#ifndef  __CONFIG_PARSER_H____
#define  __CONFIG_PARSER_H____

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sstream>
#include <fstream>
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include "Debug.h"

using namespace std;

class configParser{
	public:
		configParser(){}
		~configParser(){}
		void trim(string& str)
		{
			string::size_type pos = str.find_last_not_of(' ');
			if(pos != string::npos)
			{
				str.erase(pos + 1);
				pos = str.find_first_not_of(' ');
				if(pos != string::npos) str.erase(0, pos);
			}
			else str.erase(str.begin(), str.end());
		}

		vector < string > LoadConfInfo(const char *fn)
		{
			vector <string > args;
			ifstream infs(fn);
			if (!infs) {
				return args;
			}
			int lineNum=0;
			int commentLevel = 0;
			string line;
			while (getline(infs, line))
			{
				++lineNum;
				string stemp = line;
				int index;
				int lastLoc = 0;
				while (true) {
					index = (int) stemp.find('#', lastLoc) ;
					if (index != -1) {
						if (index > 0 && line[index-1] == '\\') {
							lastLoc = index+1;
							continue;
						} else {
							stemp = stemp.substr(0,index);
							break;
						}
					} else {
						break;
					}
				}

				if (stemp.length() == 0) {
					continue;
				}
                                trim(stemp);
				string sa, sb;
				if(stemp.length()>2)
				{
					sa = stemp.substr(0, 2);
					sb = stemp.substr(stemp.length()-2,2);
				}
				else if(stemp.length() == 2)
				{
					sa = stemp;
					sb = stemp;
				}

				if (sa == "/*") {
					++commentLevel;
					continue;
				}

				if (sb == "*/") {
					if (commentLevel == 0) {
						cerr <<  lineNum << ": extra close comment\n";
						break;
					} else {
						--commentLevel;
					}
					continue;
				}
				if (commentLevel > 0) {
					continue;
				}
				args.push_back(stemp);
			}
			return args;
		}

		map <string, string > Parser(const char *fn)
		{
			map <string, string > args;
			ifstream infs(fn);
			if (!infs) {
				return args;
			}
			int lineNum=0;
			int commentLevel = 0;
			string line;
			while (getline(infs, line))
			{
				++lineNum;
				string stemp = line;
				int index;
				int lastLoc = 0;
				while (true) {
					index = (int) stemp.find('#', lastLoc) ;
					if (index != -1) {
						if (index > 0 && line[index-1] == '\\') {
							lastLoc = index+1;
							continue;
						} else {
							stemp = stemp.substr(0,index);
							break;
						}
					} else {
						break;
					}
				}

				if (stemp.length() == 0) {
					continue;
				}

				string sa, sb;
				if(stemp.length()>2)
				{
					sa = stemp.substr(0, 2);
					sb = stemp.substr(stemp.length()-2,2);
				}
				else if(stemp.length() == 2)
				{
					sa = stemp;
					sb = stemp;
				}

				if (sa == "/*") {
					++commentLevel;
					continue;
				}

				if (sb == "*/") {
					if (commentLevel == 0) {
						cerr <<  lineNum << ": extra close comment\n";
						break;
					} else {
						--commentLevel;
					}
					continue;
				}
				if (commentLevel > 0) {
					continue;
				}
				size_t idx = stemp.find('=', 0);
				if(idx>0 && idx < stemp.length())
				{
					string key = stemp.substr(0, idx);
					string val = stemp.substr(idx + 1, stemp.length()- idx -1);
					trim(key);
					trim(val);
					args[key] = val;
				}
				else
					ERRO<<"no '=' ?" << stemp.c_str() << endl;
			}
			return args;
		}

};

#endif // __CONFIG_PARSER_H____
